﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using DevExpress.XtraTreeList;
using DevExpress.XtraTreeList.Nodes;
using DatabaseManagement.DataObjects.Interfaces;
using GeneratorManager.DatabaseABM;
using Microsoft.Win32;
using IDataObject = DatabaseManagement.DataObjects.Interfaces.IDataObject;
using DatabaseManagement.DataObjects;

namespace GeneratorManager
{
    public partial class FrmManager : XtraForm
    {
        private TreeListNode _savedFocused;
        private Boolean _needRestoreFocused;

        public FrmManager()
        {
            InitializeComponent();
        }

        #region Button Events

        private void BarItemExitItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            this.Close();
        }

        private void BarBtnNewItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            XtraForm form = new FrmNewProject();
            form.ShowDialog();
            ActiveControls();
            InitializeDatabaseExplorer();
        }

        private void BarBtnLoadItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            XtraForm form = new FrmLoadProject();
            form.ShowDialog();
            ActiveControls();

            InitializeDatabaseExplorer();
        }

        private void ActiveControls()
        {
            if (ProjectManagement.PMHelper.CurrentProject != null)
            {
                dockDatabase.Visible = true;
                dockDatabase.Visibility = DevExpress.XtraBars.Docking.DockVisibility.Visible;

            }
        }

        private void BarBtnExploradorObjetosItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            InitializeDatabaseExplorer();
        }

        #endregion

        #region DataObjects Treeview

        private void InitializeDatabaseExplorer()
        {
            if (ProjectManagement.PMHelper.CurrentProject != null)
            {
                dockDatabase.Visible = true;
                dockDatabase.Visibility = DevExpress.XtraBars.Docking.DockVisibility.Visible;
            }

            InicializeTreeView();
        }

        private void InicializeTreeView()
        {
            try
            {
                if (DatabaseManagement.DBManager.ColDatabaseManager == null)
                    return;

                if (DatabaseManagement.DBManager.ColDatabaseManager.ColInstances == null)
                    return;

                if (DatabaseManagement.DBManager.ColDatabaseManager.ColInstances.Count == 0)
                    return;
            }
            catch (Exception ex)
            {
                throw ex;
            }

            try
            {
                treeDataObjects.BeginUnboundLoad();
                treeDataObjects.Nodes.Clear();
                AppendNodes(DatabaseManagement.DBManager.ColDatabaseManager.ColInstances, null, "", "");
                ActualizeChilds(treeDataObjects.Nodes);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                treeDataObjects.EndUnboundLoad();
            }
        }

        private void AppendNodes(IEnumerable<DatabaseManagement.DataObjects.Interfaces.IDataObject> objs, TreeListNode aNode, string root, string root2)
        {
            try
            {
                Cursor currentCursor = Cursor.Current;
                Cursor.Current = Cursors.WaitCursor;

                treeDataObjects.BeginUnboundLoad();
                TreeListNode node;

                if (aNode != null) { aNode.Nodes.Clear(); }

                foreach (DatabaseManagement.DataObjects.Interfaces.IDataObject dataObject in objs)
                {
                    node = treeDataObjects.AppendNode(new object[] { dataObject.Name, dataObject}, aNode);
                    node.Tag = dataObject;
                    node.ImageIndex = GetImageIndex(dataObject);
                    node.SelectImageIndex = GetSelectImageIndex(dataObject);
                }
                treeDataObjects.EndUnboundLoad();

                Cursor.Current = currentCursor;
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format("Error agregar datos. {0}", ex.Message),
                                "Error al agregar datos a la lista.",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Error);
            }
        }

        private int GetImageIndex(IDataObject dataObject)
        {
            switch (dataObject.GetType().ToString())
            {
                case "DatabaseManagement.DataObjects.Instance":
                    return imageListDatabase.Images.IndexOfKey("iconInstance");
                    break;
                case "DatabaseManagement.DataObjects.Database":
                    return imageListDatabase.Images.IndexOfKey("iconDatabase");
                    break;
                case "DatabaseManagement.DataObjects.Table":
                    return imageListDatabase.Images.IndexOfKey("iconTable");
                    break;
                case "DatabaseManagement.DataObjects.Column":
                    return imageListDatabase.Images.IndexOfKey("iconField");
                    break;
            }
            return 0;
        }

        private int GetSelectImageIndex(IDataObject dataObject)
        {
            switch (dataObject.GetType().ToString())
            {
                case "DatabaseManagement.DataObjects.Instance":
                    return imageListDatabase.Images.IndexOfKey("iconInstance");
                    break;
                case "DatabaseManagement.DataObjects.Database":
                    return imageListDatabase.Images.IndexOfKey("iconDatabase");
                    break;
                case "DatabaseManagement.DataObjects.Table":
                    return imageListDatabase.Images.IndexOfKey("iconTable");
                    break;
                case "DatabaseManagement.DataObjects.Column":
                    return imageListDatabase.Images.IndexOfKey("iconField");
                    break;
            }
            return 0;
        }

        private void treeDataObjects_CustomDrawNodeButton(object sender, CustomDrawNodeButtonEventArgs e)
        {
            Brush backBrush = e.Cache.GetSolidBrush(Color.White);
            e.Graphics.FillRectangle(backBrush, e.Bounds);
            ControlPaint.DrawBorder(e.Graphics, e.Bounds, Color.Gray, ButtonBorderStyle.Solid);
            string displayCharacter = e.Expanded ? "-" : "+";
            StringFormat outCharacterFormat = new StringFormat();
            outCharacterFormat.Alignment = StringAlignment.Center;
            outCharacterFormat.LineAlignment = StringAlignment.Center;
            e.Graphics.DrawString(displayCharacter, new Font("Verdana", 8),
              new SolidBrush(Color.Black), e.Bounds, outCharacterFormat);

            e.Handled = true;
        }

        private void treeDataObjects_BeforeExpand(object sender, DevExpress.XtraTreeList.BeforeExpandEventArgs e)
        {
            if (e.Node != null)
            {
                if (e.Node.Tag != null)
                {
                    AppendIDataObjectsNode(e.Node, (IDataObject)e.Node.Tag);
                    ActualizeChilds(e.Node.Nodes);
                }
            }
        }

        private void ActualizeChilds(TreeListNodes nodes)
        {
            if(nodes != null)
            {
                foreach (TreeListNode node in nodes)
                {
                    AppendIDataObjectsNode(node, (IDataObject)node.Tag);
                }
            }
        }

        private void AppendIDataObjectsNode(TreeListNode node, IDataObject dataObject)
        {
            switch (dataObject.GetType().ToString())
            {
                case "DatabaseManagement.DataObjects.Instance":
                    var instance = (Instance)dataObject;
                    AppendNodes(instance.ColDatabases, node, "", "");
                    break;
                case "DatabaseManagement.DataObjects.Database":
                    var database = (Database)dataObject;
                    AppendNodes(database.ColTables, node, "", "");
                    break;
                case "DatabaseManagement.DataObjects.Table":
                    var table = (Table)dataObject;
                    AppendNodes(table.ColColumns, node, "", "");
                    break;
            }
        }

        private void treeDataObjects_FocusedNodeChanged(object sender, DevExpress.XtraTreeList.FocusedNodeChangedEventArgs e)
        {
            if (e.Node != null)
            {
                if (e.Node.Tag != null)
                {
                    AppendIDataObjectsNode(e.Node, (IDataObject)e.Node.Tag);
                    ActualizeChilds(e.Node.Nodes);
                }
            }
        }

        private void treeDataObjects_MouseUp(object sender, MouseEventArgs e)
        {
            var tree = sender as TreeList;
            if (tree == null) return;
            if (e.Button != MouseButtons.Right || ModifierKeys != Keys.None || tree.State != TreeListState.Regular)
                return;

            Point pt = tree.PointToClient(MousePosition);
            TreeListHitInfo info = tree.CalcHitInfo(pt);
            if (info.HitInfoType == HitInfoType.Cell)
            {
                tree.FocusedNode = info.Node;
                _savedFocused = tree.FocusedNode;
                _needRestoreFocused = true;
                popupMenuDatabase.ShowPopup(MousePosition);
            }
        }

        #endregion

        private void popupMenuDatabase_BeforePopup(object sender, CancelEventArgs e)
        {
            if (!(_savedFocused.Tag.GetType().ToString().Contains("DatabaseManagement.DataObjects.Table") || _savedFocused.Tag.GetType().ToString().Contains("DatabaseManagement.DataObjects.Database")))
            {
                e.Cancel = true;
            }

            if(_savedFocused.Tag.GetType().ToString().Contains("Table"))
            {
                foreach(DevExpress.XtraBars.BarItem item in popupMenuDatabase.Manager.Items)
                {
                    if(item.Name == "mnuItemNewTable")
                    {
                        item.Visibility = DevExpress.XtraBars.BarItemVisibility.Never;
                    }
                    if (item.Name == "mnuItemModifyTable")
                    {
                        item.Visibility = DevExpress.XtraBars.BarItemVisibility.Always;
                    }
                    if (item.Name == "mnuItemRenameTable")
                    {
                        item.Visibility = DevExpress.XtraBars.BarItemVisibility.Always;
                    }
                }    
            }
            else
            {
                foreach (DevExpress.XtraBars.BarItem item in popupMenuDatabase.Manager.Items)
                {
                    if (item.Name == "mnuItemModifyTable")
                    {
                        item.Visibility = DevExpress.XtraBars.BarItemVisibility.Never;
                    }
                    if (item.Name == "mnuItemNewTable")
                    {
                        item.Visibility = DevExpress.XtraBars.BarItemVisibility.Always;
                    }
                    if (item.Name == "mnuItemRenameTable")
                    {
                        item.Visibility = DevExpress.XtraBars.BarItemVisibility.Never;
                    }
                } 
            }
            
        }

        private void mnuItemNewTable_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            var frm = new GeneratorManager.DatabaseABM.FrmABMTable { MdiParent = this };
            frm.CurrentNode = _savedFocused;
            frm._createdTable = new FrmABMTable.CreatedTable(ActualizeChilds);
            frm.Show();
        }

        private void mnuItemModifyTable_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            var obj = _savedFocused.Tag;
            if (obj == null) return;

            if (obj.GetType().ToString() != (new DatabaseManagement.DataObjects.Table().GetType().ToString())) return;

            var frm = new GeneratorManager.DatabaseABM.FrmABMTable { MdiParent = this, CurrentTable = (Table)obj };
            frm.CurrentNode = _savedFocused;
            frm._createdTable = new FrmABMTable.CreatedTable(ActualizeChilds);
            frm.Show();
        }

        private void mnuItemRenameTable_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            try
            {
                var obj = _savedFocused.Tag;
                if (obj == null) return;

                if (obj.GetType().ToString() != (new DatabaseManagement.DataObjects.Table().GetType().ToString())) return;

                if (_savedFocused.ParentNode.Tag == null) return;

                if (_savedFocused.ParentNode.Tag.GetType().ToString() != (new DatabaseManagement.DataObjects.Database().GetType().ToString())) return;

                var table = (Table) obj;
                var database = (Database) _savedFocused.ParentNode.Tag;

                string result = Microsoft.VisualBasic.Interaction.InputBox("Ingrese el nuevo nombre de la tabla", "Cambiar nombre tabla", table.Name);
                if(result.Trim() != string.Empty)
                {
                    if (database.CheckExistingTable(result, table))
                    {
                        MessageBox.Show("Ya existe una tabla con ese nombre. No se guardaron los cambios.", 
                                        "La tabla ya existe en estae base de datos.", 
                                        MessageBoxButtons.OK, 
                                        MessageBoxIcon.Exclamation);
                        return;
                    }
                    table.Name = result;
                    ActualizeChilds(_savedFocused.ParentNode.Nodes);
                    treeDataObjects.FocusedNode = _savedFocused.ParentNode;
                }
            }
            catch (Exception)
            {
                throw;
            }
        }
    }
}